// This isn't the raw ASM. Obviously. // This is how I understand ASM: by translating it somewhat, to a more // readable form. If you want to see the real opcodes, you'll need to // disassemble the game. But this little pseudosyntax should be helpful // enough in *understanding* the code -- in figuring out what exactly // it does. // First, the code for "cmda6" itself. push {lr} // at 0x0806AA31 r1 = [r0 + 0x8] r2 = byte [r1] r1 += 0x1 store(r1, [r0 + 0x8]) r0 = r2 // = argument 1 call 0x0806E8D0 push {r4,lr} r4 = byte r0 // = argument 1 r0 = [0x0806E908] // = 0x0806E811 call 0x08077688 // Find the position of an ASM pointer within // an execution queue. Return the found position // or 0xFF if the pointer isn't on the queue. // IN r0 Pointer to search for // OUT r0 Zero-indexed position in queue, // or 0xFF if not found push {lr} r3 = r0 // = 0x0806E811 r2 = 0x0 r1 = [0x080776A4] // = 0x03005090 = ASM queue do { r0 = byte [r1 + 0x4] // = first metadata byte for current queue item if (r0 == 0x1) { r0 = [r1] if (r0 == r3) { return r0 = byte r2 // return: goto 0x080776B2 } } r1 += 0x28 // at 0x080776A8 r2 += 0x1 } while (r2 <= 0xF); return r0 = 0xFF // return: at 0x080776B2 r1 = byte r0 // and r0 = r0 << 0x18 if (r1 != 0xFF) { // The ASM routine we checked for is queued. r1 = getQueueItemByIndex(r0) + 0x8 // = offset of queue item's 2nd word of metadata r2 = 0x0 r0 = r1 + 0x1E do { // Clear item bytes 8 - 38 (decimal) of the queue item (reset state) storeHalfword(r2, [r0]) r0 -= 0x2 } while (r0 >= r1); // Clear done if (r4 <= 0x7) { // = argument 1 storeHalfword(r4, [r1]) // Store argument 1 in the queue item -- subroutine number to activate. } else { r0 = 0x0 // Treat invalid values as 0 storeHalfword(r0, [r1]) // ...and store them. } } return // at 0x0806E912 r0 = 0x0 return // pop {r1} ; bx r1 /* Next, we have the ASM pointer that "cmda6" tampers with. This runs on every frame and will call one of eight subroutines, the subroutine having been specified using cmda6. */ push {lr} // at 0x0806E811 r0 = byte r0 r2 = [0x0806E834] // = 0x03005090 = ASM execution queue r1 = getQueueItemByIndex(r0) // = offset: this routine's own queue item r2 = 0x8 r1 = signed halfword [r1 + r2] // = queue item metadata bytes 4 and 5 (pointer no.) r2 = [0x0806E838] // = 0x083A7310 = list of pointers to the subroutines r1 = r1 << 0x2 r1 += r2 r1 = [r1] // Pointer to the subroutine to use. call 0x081E3BAC goto [r1] // bx r1 // Possibilities: 0806E955, 0806EB55, 0806E955, 0806E955, 0806E9E1, 0806E955, 0806E955, // 0806EC41 // Subroutines 0, 2, 3, 5, 6: Nops. // Just as an aside, you could totally edit the pointer list at 0x083A7310 and replace one of these // things with your own function, to be called every single frame whenever the player is on the OW. // That way, you could do your own change-tiles-when-stepped on effects. Just sayin'. // // Oh, but if you do that, keep one of the subroutines as a nop, so you have a way to disable all // walking subroutines. // return // bx lr // at 0x0806E955 // Subroutine 1: Route 113 Ash-Grass [crippled in FireRed] push {r4,r5,lr} // at 0x0806EB55 sp -= 0x4 // We use the metadata in the ASM queue item to hold some data. I shortened the process of deriving // the offset to "getQueueItemByIndex(r0)" for brevity's sake. A look at the original ASM should // give you an idea of how it's done -- just some simple bitshifts and addition. r0 = byte r0 // = queue item number r5 = getQueueItemByIndex(r0) + 0x8 // = offset: queue item X, metadata word 2 r1 = r4 = sp + 0x2 r0 = sp // We call the below function to copy the player X- and Y-coordinates into the stack for easy // reference. call 0x0805C538 // Store the X and Y of the player-controlled OW at [r0] and [r1] // Below, we compare the newly-stored coordinates to those in the queue item metadata. Essentially, // we're checking if they've changed -- if the player has moved. If they haven't moved, then we have // nothing to process, so return. r0 = sp r2 = halfword [r0] // = player X r1 = signed halfword [r0] // = player X, signed (what's the difference?) r0 = signed halfword [r5 + 0x2] // = logged X if (r1 == r0) { // If leaving-X = logged X r1 = signed halfword [r4] // = player Y, signed r0 = signed halfword [r5 + 0x4] // = logged Y if (r1 == r0) { // If leaving-Y = logged Y sp += 0x4 // at 0x0806EBF6 return } } // We now update the queue item metadata with the new coordinates, so that when this subroutine is // called again next frame, the above check will fail. (We only run once per step taken by the player.) storeHalfword(r2, [r5 + 0x2]) // Store player X. // at 0x0806EB8E r0 = halfword [r4] storeHalfword(r0, [r5 + 0x4]) // Store player Y. // Now, we do our actual processing. r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y call 0x08058F78 // Retrieves Background Byte 2 for the tile at (X, Y) on the // current map. Also, if Background Byte 1 is odd, 0x100 is // added to the result (due to use of a bitmask). push {lr} r0 = halfword r0 // = player X r1 = halfword r1 // = player Y r2 = 0x0 call 0x08058F48 // Get the behavior bytes at (X, Y) on the current map, // use a bitmask on them, and then return the result. // IN r0 X // IN r1 Y // IN r2 Number of the bitmask to use. // OUT r0 Result push {r4,lr} r4 = r2 r4 = byte r4 r0 = halfword r0 r1 = halfword r1 call 0x08058E48 // r0 = Number of the loaded tile at (r0, r1) r1 = halfword r0 // = number of the tile the player is standing on r0 = [0x08058F74] // = 0x02036DFC = offset of current map header in RAM r0 = [r0] // = offset of current map footer r2 = r4 call 0x08059080 // Returns the behavior and background byte(s) for // the specified tile number (using the tilesets // specified by the provided map footer). If the // specified tile number is invalid (too high), // then 0xFF is returned. // // IN r0 Map footer offset // IN r1 Tile number // IN r2 One of seven bitmasks to be applied // to the tile's data bytes. // OUT r0 Byte. push {r4-r6,lr} r4 = r0 // = map footer offset r3 = halfword r1 // = tile number r5 = r3 r2 = byte r2 r6 = r2 if (r3 > 0x27F) { // if r3 is a tileset-2 tile if (r3 <= 0x3FF) { // if r3 is valid r0 = [r4 + 0x14] // = pointer to tileset 2 // opcode at 0x080590B8 r1 = [r0 + 0x14] // = pointer to tileset 2 behavior data (animations in R/S/E?) r0 = r5 << 0x2 r0 += r1 r1 = [0x080590D4] // = 0xFFFFF600 r0 += r1 r0 = [r0] // = tile bytes (WW XX YY ZZ = behav1 behav2 backg1 backg2) r1 = r6 call 0x08058F1C // at 0x080590C8 // Not too sure. Looks like we're applying // bitmasks to the tile bytes. // IN r0 Data bytes // IN r1 Number of the bitmask to use. // Backg. 2 Backg. 1 Behav. 2 Behav. 1 // ZZZZZZZZ YYYYYYYY XXXXXXXX WWWWWWWW // 00: 11111111 00000001 00000000 00000000 // 01: 00000000 00111110 00000000 00000000 // 02: 00000000 11000000 00000011 00000000 // 03: 00000000 00000000 11111100 00000000 // 04: 00000000 00000000 00000000 00000111 // 05: 00000000 00000000 00000000 00011000 // 06: 00000000 00000000 00000000 01100000 // 07: 00000000 00000000 00000000 10000000 // OUT r0 Bitmasked data bytes. push {lr} r2 = r0 // = data bytes r3 = byte r1 if (r3 <= 0x7) { r1 = [0x08058F40] // = 0x08352EF0 r0 = r3 << 0x2 r0 += r1 r0 = [r0] r2 &= r0 r0 = [0x08058F44] // = 0x08352F10 r0 = r3 + r0 r0 = byte [r0] r2 = r2 >> r0 } r0 = r2 // at 0x08058F3A return } else { // if r3 is invalid (too high) r0 = 0xFF } return // at 0x080590CC } else { r0 = [r4 + 0x10] // = pointer to tileset 1 r1 = [r0 + 0x14] // = pointer to tileset 1 behavior data (animations in R/S/E?) r0 = r3 << 0x2 r0 += r1 r0 = [r0] // = background bytes r1 = r2 call 0x08058F1C // opcode: goto 0x080590C8 (see above) return // at 0x080590CC } return // pop {r4} ; pop {r1} ; bx r1 return // pop {r1} ; bx r1 // r0 = background byte of the tile the player is standing on? // r4 = offset: stack pointer + 2 (stored player Y) r0 = byte r0 // at 0x0806EBA2 call 0x08059F50 // This appears to have been edited into FireRed r0 = 0x0 // to kill the subroutine so it can't run. return // bx lr r0 = r0 << 0x18 if (r0 == 0x0) { // If no background byte, then return. This isn't the [s]droid[/s] tile we're looking for. sp += 0x4 // at 0x0806EBF6 return } r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y call 0x08058E48 // r0 = Number of the loaded tile at (r0, r1) r1 = [0x0806EBDC] // = 0x0000020A = Route 113 tileset: ash tall grass r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y if (r0 == r1) { r2 = [0x0806EC00] // This pretty much never happens. } else { r2 = [0x0806EBE0] // = 0x00000212 = Route 113 tileset: normal tall grass } r3 = 0x4 call 0x080DC23C // No clue what this code does. It may have something // to do with queueing an (animated?) change to the // ash-covered grass tile we've stepped on. // IN r0 Tile x-coordinate // IN r1 Tile Y-coordinate // IN r2 A block number in a tileset // IN r3 Unknown. push {r4,lr} r2 = halfword r2 r4 = [0x080DC26C] // = 0x020386E0 r0 = halfword r0 // = X store(r0, [r4]) r1 = halfword r1 // = Y store(r1, [r4 + 0x4]) r0 = 0x52 store(r0, [r4 + 0x8]) r0 = 0x1 store(r0, [r4 + 0xC]) store(r2, [r4 + 0x10]) r3 = halfword r3 store(r3, [r4 + 0x14]) r0 = 0x7 call 0x08083444 // I think that this function is broken // outside of R/S/E. The tables it uses // are still intact, but the contained // pointers don't seem to point to valid // data. Maybe it's connected to the // Soot Sack functionality somehow? push {r4,r5,lr} sp -= 0x8 r0 = r4 = byte r0 call 0x080837D0 r0 = [0x08083484] // = 0x081D96AC = a list of pointers? r4 = r4 << 0x2 r4 += r0 r0 = [r4] store(r0, [sp]) r4 = sp + 0x4 r5 = [0x0808348] // = 0x083CBE30 = a list of pointers? do { r0 = [sp] r0 = byte [r0] r0 = r0 << 0x2 r0 += r5 r2 = [r0] r0 = sp r1 = r4 call 0x081E3BB0 goto [r2] // bx r2 r0 = r0 << 0x18 } while (r0 != 0x0); r0 = [sp + 0x4] sp += 0x8 return return sp += 0x4 // goto 0x0806EBF6 return // pop {r4,r5} ; pop {r0} ; bx r0 // Subroutine 4: Icefall Cave Cracked Ice push {r4-r6,lr} // at 0x0806E9E1 sp -= 0x4 // As before, I've used shorthand for grabbing the queue item. r0 = byte r0 r5 = getQueueItemByIndex(r0) + 0x8 // = offset: current queue item, metadata word 2 // This next opcode tells us what we're actually doing. If 0x1, we check if the player's // standing on a tile we need to act on. If greater than 0x1, then we've already queued a // change to be executed after a certain number of frames. r0 = signed halfword [r5 + 0x2] if (r0 == 0x1) { r1 = r4 = sp + 2 // at 0x0806EA2A r0 = sp call 0x0805C538 // see above r0 = sp r2 = halfword [r0] r1 = signed halfword [r0] // player X r0 = signed halfword [r5 + 0x4] if (r1 == r0) { r1 = signed halfword [r4] r0 = signed halfword [r5 + 0x6] if (r1 == r0) { sp += 0x4 // at 0x0806EB42 return } } storeHalfword(r2, [r5 + 0x4]) // at 0x0806EA52 r0 = halfword [r4] storeHalfword(r0, [r5 + 0x6]) r0 = signed halfword [sp] // player X r1 = signed halfword [r4] // player Y r2 = 0x0 call 0x08058F78 // Get data bytes for tile (and apply bitmask 0x0) r0 = r6 = byte r0 call 0x08059FF4 // Return boolean result depending on if // r0 (behavior byte of tile player is // standing on) is 0x26. push {lr} r0 = byte r0 if (r0 == 0x26) { return r0 = 0x1 } return r0 = 0x0 r0 = byte r0 if (r0 == 0x1) { // The player is standing on a tile with behavior byte 0x26 -- an uncracked fragile ice // tile. r0 = signed halfword [sp] // player X r1 = signed halfword [r4] // player Y call 0x0806E958 // We're looping through a set of 8 // coordinate pairs listed at 0x083A7330 // and comparing them to the player's // position. Why? // // I don't know WHY we're doing it, but // I can tell you that the coordinate // pairs are a perfect match to each // breakable ice tile in Icefall Cave. // I THINK we're actually setting temp // flags for each ice tile (to be read // by a special in a level script), so // that the tiles' states are saved when // the player saves the game. // // That's totally just a guess, though. // I'd have to see the special to be sure. // // IN r0 Player X // IN r1 Player Y push {r4,r5,lr} r3 = 0x0 r4 = [0x0806E988] // = 0x083A7330 r5 = halfword r0 r1 = halfword r1 do { r2 = r3 << 0x1 // at 0x0806E966 r0 = r2 + r4 r0 = byte [r0] r0 += 0x7 // Add 7 to sync up with loaded map data. if (r0 != r5) { // Compare player X. r0 = r3 + 0x1 // at 0x0806E98C r3 = byte r0 if (r3 <= 0x8) { continue // goto 0x0806E966 } return // Return if we've checked more than nine pairs. } r0 = r2 + r4 + 0x1 r0 = byte [r0] r0 += 0x7 // Add 7 to sync up with loaded map data. if (r0 != r1) { // Compare player Y. r0 = r3 + 0x1 // at 0x0806E98C r3 = byte r0 if (r3 > 0x8) { // Return if we've checked more than nine pairs. return } } } while (r0 != r1); // If we haven't returned by now, then the player is standing on one of the // listed tiles. At this point we set a flag -- I think one of the temporary // flags starting at 0x1. r0 = r3 + 0x1 call 0x0806E680 // sets the flag specified by r0 -- probably one of the temp flags return // goto 0x0806E996 r0 = 0x4 storeHalfword(r0, [r5 + 0xC]) // Do nothing for the next four frames... r0 = 0x2 // ...and then queue a tile change (uncracked -> cracked). } else { // We need to check if the player is standing on a tile with behavior byte 0x27 -- a // cracked fragile ice tile. r0 = r6 // at 0x0806EA8E call 0x0805A008 // Return boolean result depending on if // r0 (behavior byte of tile player is // standing on) is 0x27. push {lr} r0 = byte r0 if (r0 == 0x27) { return r0 = 0x1 } return r0 = 0x0 r0 = byte r0 if (r0 != 0x1) { // The player's not on a tile we're concerned with. Return. sp += 0x4 // at 0x0806EB42 return } r0 = 0x4 storeHalfword(r0, [r5 + 0xC]) // Do nothing for the next four frames... r0 = 0x3 // ...and then queue a tile change (cracked -> hole). } // Here, we store the queued tile change along with the player's current X and Y (the tiles to be // changed?). storeHalfword(r0, [r5 + 0x2]) // store queued change // at 0x0806EAA2 r0 = halfword [sp] // = player X storeHalfword(r0, [r5 + 0x8]) // store X r0 = halfword [r4] // = player Y storeHalfword(r0, [r5 + 0xA]) // store Y } else if (r0 > 0x1) { // Okay, so we have a queued tile change that we need to take care of. Let's do this! if (r0 == 0x2) { // at 0x0806EA08 // Queued change: uncracked to cracked. r1 = halfword [r5 + 0xC] // = frame delay // at 0x0806EAB0 r0 = signed halfword [r5 + 0xC] if (r0 != 0x0) { r0 = r1 - 0x1 // at 0x0806EAFE // Iterate by one frame storeHalfword(r0, [r5 + 0xC]) // Store the new delay goto 0x0806EB42 // Return sp += 0x4 // at 0x0806EB42 return } // No delay remaining. Change that tile! r1 = sp r0 = halfword [r5 + 0x8] storeHalfword(r0, [r1]) // Save player X r4 = sp + 0x2 r0 = halfword [r5 + 0xA] storeHalfword(r0, [r4]) // Save player Y r0 = 0x24 call 0x080722CC // Play sound 0x24 r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y r2 = [0x0806EAF0] // = 0x0000035A = cracked ice tile call 0x08058FA4 // Change tile at (r0, r1) to tile number r2 r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y call 0x0805A8E8 push {r4,r5,lr} r4 = r0 // = player X r5 = r1 // = player Y r0 = [0x0805A914] // = 0x03000E90 = ASM execution queue offset r1 = r4 // = player X r2 = r5 // = player Y call 0x0805AAE8 // Too lazy to look into this. r1 = r0 if (r1 >= 0x0) { r0 = [0x0805A918] // = 0x02036DFC r0 = [r0] r1 = halfword r1 r2 = r4 r3 = r5 call 0x0805A948 push {r4-r7,lr} r7 = r8 push {r7} r5 = r0 r0 = r6 = r2 r7 = r3 r8 = r1 = halfword r1 r1 = r7 call 0x08058E48 // see above (return tile the player is standing on) r4 = halfword r0 if (r4 > 0x400) { // Treat invalid tiles as Tile 0 r4 = 0x0 } if (r4 > 0x27F) { // part of tileset 2? r0 = [r5 + 0x14] // at 0x0805A980 r5 = [r0 + 0xC] r1 = [0x0805A9B0] // = 0xFFFFFD80 r0 = r4 + r1 r4 = halfword r0 } else { // part of tileset 1. r0 = [r5 + 0x10] r5 = [r0 + 0xC] } r0 = halfword r6 // at 0805A98C r1 = halfword r7 call 0x08058F8C push {lr} r0 = halfword r0 r1 = halfword r1 r2 = 0x6 call 0x08058F48 // see above r0 = byte r0 return r0 = byte r0 r1 = r4 << 0x4 r1 = r5 + r1 r2 = r8 call 0x0805A9B4 // This has something to do with saving to the DMA-protected save // blocks in RAM. Is this saving the tile changes somehow? push {r4,lr} r4 = r1 r2 = halfword r2 if (r0 == 0x1) { r0 = [0x0805AA60] // = 0x0300500C // at 0x0805AA0C r0 = [r0] // = [0x0300500C] r3 = r2 << 0x1 r0 = r3 + r0 r1 = halfword [r4] storeHalfword(r1, [r0]) r1 = halfword [r4 + 0x2] storeHalfword(r1, [r0 + 0x2]) r2 = r0 r2 += 0x40 r1 = halfword [r4 + 0x4] storeHalfword(r1, [r2]) r0 += 0x42 r1 = halfword [r4 + 0x6] storeHalfword(r1, [r0]) r0 = [0x0805AA64] // = 0x03005014 r0 = [r0] r0 = r3 + r0 r1 = halfword [r4 + 0x8] storeHalfword(r1, [r0]) r1 = halfword [r4 + 0xA] storeHalfword(r1, [r0 + 0x2]) r2 = r0 r2 += 0x40 r1 = halfword [r4 + 0xC] storeHalfword(r1, [r2]) r0 += 0x42 r1 = halfword [r4 + 0xE] storeHalfword(r1, [r0]) r0 = [0x0805AA68] // = 0x03005018 r0 = [r0] r3 = r3 + r0 r1 = 0x0 storeHalfword(r1, [r3]) storeHalfword(r1, [r3 + 0x2]) r0 = r3 r0 += 0x40 storeHalfword(r1, [r0]) r3 += 0x42 storeHalfword(r1, [r3]) goto 0x0805AABE } else if (r0 > 0x1) { // at 0x0805A9CA } else if (r0 == 0x0) { // at 0x0805AA6C } else { // at 0x0805AABE } return } return // at 0x0805A90E // Here, we return the state byte from >1 (queued change) to 1 (listen for player steps // and react to certain tiles). goto 0x0806EB3E r0 = 0x1 storeHalfword(r0, [r5 + 0x2]) } else if (r0 == r3) { // Queued change: cracked to hole. r1 = halfword [r5 + 0xC] // at 0x0806EAF4 r0 = signed halfword [r5 + 0xC] // = frame delay // If there's no frame delay: if (r0 == 0x0) { r1 = sp // at 0x0806EB04 r0 = halfword [r5 + 0x8] storeHalfword(r0, [r1]) // store player X for easy reference r4 = sp + 0x2 r0 = halfword [r5 + 0xA] storeHalfword(r0, [r4]) // store player Y for easy reference r0 = 0x25 call 0x080722CC // Play sound 0x25. r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y r2 = [0x0806EB4C] // = 0x0000035B = hole tile call 0x08058FA4 // Change tile at (r0, r1) to tile number r2 r0 = signed halfword [sp] // = player X r1 = signed halfword [r4] // = player Y call 0x0805A8E8 r0 = [0x0806EB50] // = 0x00004001 r1 = 0x1 call 0x0806E584 // Need to check, but I think this sets script variable r0 to r1. r0 = 0x1 // Here, we return the state byte from >1 (queued change) to 1 (listen for player steps // and react to certain tiles). Then, we return. storeHalfword(r0, [r5 + 0x2]) sp += 0x4 return } // If there's a frame delay, we tick off another frame. r0 = r1 - 0x1 storeHalfword(r0, [r5 + 0xC]) } } else if (r0 == 0x0) { // I think this only happens when the subroutine is switched on and runs for the first time. // Looks like we store the current tile and then signal to start listening for the next step // the player takes. r4 = sp + 2 // at 0x0806EA12 r0 = sp r1 = r4 call 0x0805C538 // see above r0 = halfword [sp] // = player X storeHalfword(r0, [r5 + 0x4]) // Store player X in the queue item metadata. r0 = halfword [r4] // = player Y storeHalfword(r0, [r5 + 0x6]) // Store player Y in the queue item metadata. goto 0x0806EB3E // Revert to step-listening state. r0 = 0x1 storeHalfword(r0, [r5 + 0x2]) } sp += 0x4 // at 0x0806EB42 return // Subroutine 7: Granite Cave/Sky Pillar Cracked Floors [crippled in FireRed] // Admittedly I haven't looked this one over as thoroughly as Subroutines 1 and 4. It looks like // the primary differences between it and Subroutine 4 are that 7 handles two-state tiles (while // 4 handles three-state tiles) and 7 allows the queueing of multiple changes (presumably to // account for the Mach Bike "outrunning" the changes). push {r4-r7,lr} // at 0x0806EC41 sp -= 0x4 r0 = byte r0 // = queue item number r5 = getQueueItemByIndex(r0) + 0x8 // = offset: queue item X, metadata word 2 r4 = sp + 2 r0 = sp r1 = r4 call 0x0805C538 // Store player coords at [r0], [r1] for easy reference r0 = signed halfword [sp] // r0 = player X r1 = signed halfword [r4] // r1 = player Y r2 = 0x0 call 0x08058F78 // Get data bytes for tile (and apply bitmask 0x0) r7 = halfword r0 r1 = halfword [r5 + 0x8] r0 = signed halfword [r5 + 0x8] r6 = r4 // = offset: player Y if (r0 != 0x0) { r0 = r1 - 0x1 storeHalfword(r0, [r5 + 0x8]) r0 = r0 << 0x10 if (r0 == 0x0) { r0 = signed halfword [r5 + 0xA] r1 = signed halfword [r5 + 0xC] call 0x0806EC04 push {r4,r5,lr} r0 = r5 = halfword r0 // = player X r1 = r4 = halfword r1 // = player Y call 0x08058E48 // r0 = number of the tile the player is standing on r1 = [0x0806EC38] // = 0x0000022F = Cracked floor r2 = [0x0806EC3C] // = 0x00000237 = A braille tile? if (r0 == r1) { // Is the player standing on a cracked floor tile? r2 -= 0x31 // = 0x00000206 = Hole } r0 = r5 // = player X r1 = r4 // = player Y call 0x08058FA4 // Change tile at (r0, r1) to tile number r2 r0 = r5 // = player X r1 = r4 // = player Y call 0x0805A8E8 // see above return } } r1 = halfword [r5 + 0xE] // at 0x0806EC92 r0 = signed halfword [r5 + 0xE] if (r0 != 0x0) { r0 = r1 - 0x1 storeHalfword(r0, [r5 + 0xE]) r0 = r0 << 0x10 if (r0 == 0x0) { r0 = signed halfword [r5 + 0x10] r1 = signed halfword [r5 + 0x12] call 0x0806EC04 // If player's on cracked floor, change to hole. // See above. } } // Below, we compare the player's current coordinates to those in the queue item metadata. Essentially, // we're checking if they've changed -- if the player has moved. If they haven't moved, then we have // nothing to process, so return. r0 = sp // at 0x0806ECB2 r2 = halfword [r0] // = player X r1 = signed halfword [r0] // = player X r0 = signed halfword [r5 + 0x4] // = logged X if (r1 == r0) { r1 = signed halfword [r6] // = player Y r0 = signed halfword [r5 + 0x6] // = logged Y if (r1 == r0) { sp += 0x4 // at 0x0806ED2E return } } // Log the player's coordinates. storeHalfword(r2, [r5 + 0x4]) // Store player X. // at 0x0806ECCE r4 = r6 r0 = halfword [r4] storeHalfword(r0, [r5 + 0x6]) // Store player Y. r0 = byte r7 call 0x0805A1D8 // This appears to have been edited into FireRed r0 = 0x0 // to kill this subroutine so it can't actually return // bx lr // have an effect or change anything. r0 = r0 << 0x18 if (r0 == 0x0) { sp += 0x4 // at 0x0806ED2E return } call 0x080BD674 push {lr} sp -= 0x8 r1 = [0x080BD69C] // = 0x083E7D1C r0 = sp r2 = 0x6 call 0x081E5E78 r2 = [0x080BD6A0] // = 0x02037078 = player speed r1 = byte [r2] r0 = 0x2 & r1 if (r0 == 0x0) { r0 = 0x4 & r1 // at 0x080BD6A4 if (r0 != 0x0) { r0 = 0x3 sp += 0x8 // goto 0x080BD6BE return } r0 = 0x88 & r1 // at 0x080BD6B0 if (r0 == 0x0) { r0 = 0x1 sp += 0x8 // goto 0x080BD6BE return } r0 = 0x2 // at 0x080BD6BC sp += 0x8 // at 0x080BD6BE return } r0 = byte [r2 + 0xA] // = 0x02037082 = Unknown or R/S/E only. Related to player mvmt. r0 = r0 << 0x1 r0 += sp r0 = signed halfword [r0] sp += 0x8 // goto 0x080BD6BE return r0 = halfword r0 if (r0 != 0x4) { r0 = [0x0806ED14] // = 0x00004030 (script var?) r1 = 0x0 call 0x0806E584 // Are we setting var 0x4030 to 0x0000? } r0 = signed halfword [r5 + 0x8] // at 0x0806ECF8 if (r0 != 0x0) { r0 = signed halfword [r5 + 0xE] // at 0x0806ED18 if (r0 == 0x0) { r0 = 0x3 storeHalfword(r0, [r5 + 0xE]) r0 = halfword [sp] // = player X storeHalfword(r0, [r5 + 0x10]) r0 = halfword [r6] // = player Y storeHalfword(r0, [r5 + 0x12]) } sp += 0x4 // at 0x0806ED2E return } r0 = 0x3 storeHalfword(r0, [r5 + 0x8]) r0 = halfword [sp] // = player X storeHalfword(r0, [r5 + 0xA]) // Store player X. r0 = halfword [r4] // = player Y storeHalfword(r0, [r5 + 0xC]) // Store player Y. goto 0x0806ED2E sp += 0x4 return return // pop {r0} ; bx r0